unit adaptors;
{$IFDEF FPC}
{$MODE DELPHI}
{$DEFINE UNICODE}
{$ENDIF}
interface
uses BASS, SysUtils, adapt_consts, Classes;
var
  plug_cnt: DWORD = 0;
  plug_alloccnt: DWORD  = 1;
  plug_lst: array of TPLUGIN_REC;
  media_names: TstringList;
procedure ENGINE_INIT;
procedure ENGINE_FREE;
procedure ENGINE_LOADPLUGIN(const file_name: string);
procedure ENGINE_LOADALLPLUGINS;
procedure ENGINE_SETATTRIBUTE(const Hndl: Hstream; const PARAMS: DWORD; const VALUE: FLOAT);
procedure ENGINE_SETVOLUME(const Volume: Float);
procedure ENGINE_EQUALISER_INIT(const Hndl: Hstream; var fx: Hfx);
procedure ENGINE_Channel_GETDATA(const Hndl: Hstream; target: Pointer; const len: Cardinal);
procedure ENGINE_Channel_Pause(const Hndl: Hstream);
procedure ENGINE_Channel_Play(const Hndl: Hstream; const Replay: boolean);
procedure ENGINE_Channel_SetPosition(const hndl: Hstream; const pos, mode: Qword);
procedure ENGINE_Eq_SETFREQ(const Hndl: HsTream; var FX: HFX; const Freq: Word; Const Value: SmallInt);
procedure ENGINE_Terminate_Channel(const hndl: Hstream);


function ENGINE_GETATTRIBUTE(const hndl: Hstream; const PARAMS: DWORD): FLOAT;
function ENGINE_GETVOLUME: FLOAT;
function ENGINE_GETCPU: FLOAT;
function ENGINE_Create_channel(const filename: string; const faked: boolean): Hstream;
function ENGINE_Get_length(const hndl: Hstream): Float;
function ENGINE_Channel_BYTES2SECONDS(const hndl: Hstream; const pos: QWORD): Double;
function ENGINE_Cannel_GETPOSITION(const Hndl: Hstream; const Mode: DWORD): QWORD;
function ENGINE_Channel_SECONDS2BYTES(const hndl: Hstream; const pos: Double): QWORD;
function Engine_pluginGetInfo(const plugin_hndl: DWORD): ENGINE_PPLUGIN;

implementation
uses Pl_consts, utils;


function ENGINE_Create_channel(const filename: string; const faked: boolean): Hstream;
var
  hndl: Hstream;
begin
  if not fileExists(filename) then
      exit;
  hndl := Bass_StreamCreateFile(False, pchar(filename), 0, 0, 0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
  if (not faked) and( hndl <> 0) then
    BAss_channelPlay(hndl, false);
  ENGINE_Create_Channel := hndl;
  //utils._Error('BASS_ERROR' + inttostr(BASS_ErrorGetCode));
end;

procedure ENGINE_EQUALISER_INIT(const Hndl: Hstream; var fx: Hfx);
begin
  fx := BASS_ChannelSetFX(hndl, BASS_FX_DX8_PARAMEQ, 1);
end;

procedure ENGINE_LOADALLPLUGINS;
var
  dir: string;
  p_lst: PstringList;
  i: longint;
  lst: TstringList;
begin
  dir := GetCurrentDir + ENGINE_PLUGINSDIR;
  p_lst := utils.get_Files(dir, ENGINE_PLUGINSFILT);
  if (p_lst = nil) then
  begin
    _ERROR('Can`not find plugins');
    exit;
  end;
  lst := p_lst^;
  for i := 0 to lst.count - 1 do
  begin
    ENGINE_LOADPLUGIN(lst.Strings[i]);
  end;
  lst.FreeInstance;
  lst := nil;
end;

procedure ENGINE_FREEPLUGIN(const hndl: DWORD);
begin
  BASS_PLUGINFREE(hndl);
end;

procedure ENGINE_FREEALLPLUGINS;
begin
  BASS_PLUGINFREE(0);
end;

function Engine_pluginGetInfo(const plugin_hndl: DWORD): ENGINE_PPLUGIN;
begin
  Engine_pluginGetInfo := BASS_pluginGetInfo(plugin_hndl);
end;

procedure ENGINE_LOADPLUGIN(const file_name: string);
var
  Plugin_Info: ENGINE_PPLUGIN;
  plugin_hndl: bass.HPlugin;
  i: Longint;
  
  procedure RegisterPlugin(const fname: string; const hndl: DWORD);
  begin
    inc(plug_cnt);
    if (plug_cnt > plug_allocCnt) then
    begin
      plug_allocCnt := plug_allocCnt * 2;
      SetLength(plug_lst, plug_allocCnt);
    end;
    plug_lst[plug_cnt - 1].pl_fname := pchar(fname);
    plug_lst[plug_cnt - 1].pl_hndl := hndl;
  end;
begin
  //BASS_
  plugin_hndl := BASS_PluginLoad(pchar(file_name), 0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
  if (plugin_hndl <> 0) then
  begin
    Plugin_Info := pointer(Engine_pluginGetInfo(plugin_hndl));
    for i := 0 to plugin_Info.formatc - 1 do
    begin
      filt_playable := filt_playable + '|' + plugin_Info.Formats[i].name + ' '
      + ' (' + plugin_Info.Formats[i].exts + ') , ' + file_name + '|' +
      plugin_Info.Formats[i].exts;     //Update Filter for playable files
      sp_exts.Append(plugin_Info.Formats[i].exts);     //Update Filter for utils list
      media_names.append(plugin_Info.Formats[i].name);
    end;
    RegisterPlugin(file_name, plugin_hndl);
  end;
end;

procedure ENGINE_INIT;
begin
  if not bass_init(-1, 44100, 0, 0, nil) then
  begin
    write('Cant init bass');
    halt;
  end;
end;

procedure ENGINE_FREE;
begin
  bass_Free;
end;

function ENGINE_Channel_BYTES2SECONDS(const hndl: Hstream; const pos: QWORD): Double;
begin
  ENGINE_CHANNEL_BYTES2SECONDS := bass_channelbytes2seconds(hndl, pos);
end;

function ENGINE_Cannel_GETPOSITION(const Hndl: Hstream; const Mode: DWORD): QWORD;
begin
  ENGINE_Cannel_GETPOSITION := bass_channelgetPosition(hndl, Mode);
end;

function ENGINE_Channel_SECONDS2BYTES(const hndl: Hstream; const pos: Double): QWORD;
begin
  ENGINE_Channel_SECONDS2BYTES := bass_channelseconds2bytes(hndl, pos);
end;

procedure ENGINE_Channel_GETDATA(const Hndl: Hstream; target: Pointer; const len: Cardinal);
begin
  BASS_CHannelGetData(hndl, target, len);
end;

function ENGINE_GETATTRIBUTE(const hndl: Hstream; const PARAMS: DWORD): FLOAT;
var
  res: FLOAT;
begin
  ENGINE_GETATTRIBUTE := -1;
  if bass_ChannelGetAttribute(hndl, Params, res) then
    ENGINE_GETATTRIBUTE := res;
end;

procedure ENGINE_SETATTRIBUTE(const Hndl: Hstream; const PARAMS: DWORD;
  const VALUE: FLOAT);
begin
  bass_channelsetattribute(Hndl, Params, Value);
end;

procedure ENGINE_Channel_Pause(const Hndl: Hstream);
begin
   Bass_ChannelPause(Hndl);
end;

procedure Engine_SETVOLUME(Const volume: Float);
begin
  BASS_SETVOLUME(volume);
end;

function ENGINE_GETVOLUME: FLOAT;
begin
  ENGINE_GETVOLUME := BASS_GETVOLUME; 
end;

procedure ENGINE_Channel_Play(const Hndl: Hstream; const Replay: Boolean);
begin
  Bass_ChannelPlay(Hndl, Replay);
end;

procedure ENGINE_Channel_SetPosition(const hndl: Hstream; const pos, mode: Qword);
begin
  bass_channelsetposition(hndl, pos, mode);
end;

function ENGINE_GETCPU: FLOAT;
begin
  ENGINE_GETCPU := BASS_GETCPU;
end;

procedure ENGINE_Terminate_Channel(const hndl: Hstream);
begin
  if (hndl = 0) then exit;
 // Bass_MusicFree(hndl);
  BAss_StreamFree(hndl);
end;

procedure ENGINE_Eq_SETFREQ(const Hndl: HsTream;var FX: HFX; const Freq: Word; Const Value: SmallInt);
var
   PrEf: BASS_DX8_PARAMEQ;
begin
  BASS_FXGETPARAMETERS(FX, @PrEf);
  PrEf.fCenter := Freq;
  PrEf.FGain := Value;
  BASS_FXSetParameters(FX, @PrEf);
end;

function ENGINE_Get_Length(const hndl: Hstream): Float;
var
  curlen: Cardinal;
  //curlen: Float;
begin
  curlen := Bass_Channelgetlength(hndl, BASS_POS_BYTE);
  ENGINE_Get_Length := BASS_ChannelBytes2Seconds(hndl, curlen);
end;
initialization
  media_names := TstringList.Create;
  SetLength(plug_lst, plug_alloccnt);
finalization
  media_names.freeInstance;
  ENGINE_FREEALLPLUGINS;
  //ENGINE_FREE;
end.